#ifndef ECDSA_H
#define ECDSA_H

#include <sstream>

#include "signature_manager.h"
#include "GMPInt.h"

struct EllipticCurve_point {
    GMPInt x;
    GMPInt y;
    bool is_infinity; // 显式标识无穷远点

    // 默认构造为无穷远点
    EllipticCurve_point() : x(0), y(0), is_infinity(true) {}

    // 构造普通点
    EllipticCurve_point(const mpz_t x, const mpz_t y)
        : x(x), y(y), is_infinity(false) {}

    // 显式构造无穷远点
    static EllipticCurve_point infinity() {
        EllipticCurve_point p;
        p.is_infinity = true;
        return p;
    }

    std::string to_str() const {
        if (is_infinity) {
            return "INF";  // 无穷远点标识符
        }

        return x.to_str() + "," + y.to_str();
    }

    void set_by_str(const std::string& str) {
        // 处理无穷远点
        if (str == "INF") {
            is_infinity = true;
            x = 0;
            y = 0;
            return;
        }

        // 解析普通点
        size_t comma_pos = str.find(',');
        if (comma_pos == std::string::npos || comma_pos == 0 || comma_pos == str.length()-1) {
            throw std::invalid_argument("Invalid point format: " + str);
        }

        // 分割坐标
        std::string x_str = str.substr(0, comma_pos);
        std::string y_str = str.substr(comma_pos + 1);

        // 设置坐标
        x.set_by_str(x_str);
        y.set_by_str(y_str);

        is_infinity = false;
    }

};

struct EllipticCurve {
    GMPInt a;
    GMPInt b;
    GMPInt p;
    EllipticCurve_point g;  // 基点
    GMPInt n;               // 基点G的阶
    GMPInt h;               // 余因子

    EllipticCurve() = default;
    EllipticCurve(const mpz_t a,
        const mpz_t b,
        const mpz_t p,
        const mpz_t x,
        const mpz_t y,
        const mpz_t n,
        const mpz_t h)
        : a(a), b(b), p(p), g(x, y), n(n), h(h) {}

    std::string to_str() const {
        std::ostringstream oss;
        // 序列化核心参数
        oss << a.to_str() << ";"
            << b.to_str() << ";"
            << p.to_str() << ";"
            << g.to_str() << ";"
            << n.to_str() << ";"
            << h.to_str();
        return oss.str();
    }

    void set_by_str(const std::string& str) {
        std::vector<std::string> parts;
        std::istringstream iss(str);
        std::string part;

        // 按分号分割主要参数
        while (std::getline(iss, part, ';')) {
            parts.push_back(part);
        }

        // 验证参数完整性
        if (parts.size() != 6) {
            throw std::invalid_argument("Invalid EllipticCurve string format");
        }

        // 解析基础参数
        a.set_by_str(parts[0]);
        b.set_by_str(parts[1]);
        p.set_by_str(parts[2]);

        // 解析基点坐标
        g.set_by_str(parts[3]);

        // 解析其他参数
        n.set_by_str(parts[4]);
        h.set_by_str(parts[5]);
    }
};


struct ECDSA_privatekey {
    GMPInt d; // 私钥

    ECDSA_privatekey() = default;
    ECDSA_privatekey(const mpz_t d) : d(d) {}

    void set_by_str(const std::string& str){
        std::istringstream ss{str};
        std::string item;
        std::getline(ss, item, ',');
        mpz_set_str(d, item.c_str(), 10);
    }

    std::string to_str() const {
        char* str1 = mpz_get_str(nullptr, 10, d);
        std::string result(str1);
        free(str1);
        return result;
    }
};

struct ECDSA_publickey {
    EllipticCurve_point Q; // 公钥

    ECDSA_publickey() = default;
    ECDSA_publickey(const EllipticCurve_point& Q) : Q(Q) {}

    void set_by_str(const std::string& str){
        Q.set_by_str(str);
    }

    std::string to_str() const {
        return Q.to_str();
    }
};



struct ECDSA_publicparameter {
    EllipticCurve ellipticcurve;
    bool is_valid = false;

    ECDSA_publicparameter() = default;
    ECDSA_publicparameter(const EllipticCurve& ellipticcurve) : ellipticcurve(ellipticcurve) {}

    std::string to_str() const {
        std::string result = ellipticcurve.to_str();
        return result;
    }
    void set_by_str(const std::string& str) {
        ellipticcurve.set_by_str(str);
        is_valid = true;
    }
};

struct ECDSA_signature {
    GMPInt r;
    GMPInt s;

    ECDSA_signature() = default;
    ECDSA_signature(const mpz_t r, const mpz_t s) : r(r), s(s) {}

    std::string to_str() const {
        std::string result = r.to_str();
        result += "," + s.to_str();
        return result;
    }
    void set_by_str(const std::string& str) {
        std::istringstream ss{ str };
        std::string item;
        std::getline(ss, item, ',');
        r.set_by_str(item);

        std::getline(ss, item, ',');
        s.set_by_str(item);
    }
};

template<typename curve_name>
class ECDSA : public SignatureAlgorithm<
    ECDSA_privatekey,
    ECDSA_publickey,
    ECDSA_publicparameter,
    ECDSA_signature> {
public:
    void generatepublicparameters(ECDSA_publicparameter& publicParameters) override;

    void generateKeyPair(
        ECDSA_privatekey& privatekey,
        ECDSA_publickey& publickey,
        ECDSA_publicparameter& publicparameter) override;

    ECDSA_signature sign(
        const PlainMessage& message,
        const ECDSA_privatekey& privatekey,
        const ECDSA_publicparameter& publicparameter) override;

    bool verify(
        const PlainMessage& message,
        const ECDSA_publickey& publickey,
        const ECDSA_publicparameter& publicparameter,
        const ECDSA_signature& signature) override;
};

template<typename curve_name>
struct ECDSA_type_traits {
    using algo = ECDSA<curve_name>;
    using private_key = ECDSA_privatekey;
    using public_key = ECDSA_publickey;
    using params = ECDSA_publicparameter;
    using signature = ECDSA_signature;
};



// 用于模板特化的标签类型
struct secp256k1_tag {};
struct prime256v1_tag {};
struct secp384r1_tag {};

extern template class ECDSA<secp256k1_tag>;
extern template class ECDSA<prime256v1_tag>;
extern template class ECDSA<secp384r1_tag>;



#endif // ECDSA_H